package cn.cubix.flow.controller.userprms;

import cn.cubix.flow.entity.*;
import cn.cubix.flow.mapper.WfPrmsUserMapper;
import cn.cubix.flow.mapper.WfRoleUserMapper;
import cn.cubix.flow.security.SecurityService;
import cn.cubix.flow.service.WfPrmsService;
import cn.cubix.flow.service.WfRoleService;
import cn.cubix.flow.service.WfUserService;
import cn.cubix.flow.util.Result;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@RestController
@RequestMapping("/api/userprms/user")
@RequiredArgsConstructor(onConstructor=@__({@Autowired,@Lazy}))
public class WfUserApi {

    private final WfUserService wfUserService;
    private final WfRoleService wfRoleService;
    private final WfPrmsService wfPrmsService;
    private final SecurityService securityService;
    private final WfRoleUserMapper wfRoleUserMapper;
    private final WfPrmsUserMapper wfPrmsUserMapper;

    /** 分页查询系统用户 */
    @PostMapping("/page")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_PAGE')")
    public Object page(@RequestBody JSONObject body){
        long current = 1L, size = 10L, total = 0L;
        if(body.containsKey("page")){
            JSONObject page = body.getJSONObject("page");
            current = page.getLong("current",current);
            size = page.getLong("size",size);
        }
        IPage<WfUser> page = wfUserService.page(new Page<>(current,size));
        page.getRecords().forEach(wfUser -> {wfUser.setPassword(null);});
        return Result.SUCCESS(page.getRecords(),"查询成功").setPage(current,size,page.getTotal());
    }

    /** 新建系统用户 */
    @PostMapping("/create")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_CREATE')")
    public Object create(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("保存失败");
        if(body.containsKey("record")){
            JSONObject record = body.getJSONObject("record");
            WfUser wfUser = record.toBean(WfUser.class);
            wfUser.setPassword(securityService.encodePassword(wfUser.getPassword()));
            boolean saveResult = wfUserService.save(wfUser);
            if(saveResult){
                result.toSuccess().setMessage("保存成功");
            }
        }
        return result;
    }

    /** 删除系统用户 */
    @DeleteMapping("/delete")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_DELETE')")
    public Object delete(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("删除失败");
        if(body.containsKey("params")){
            JSONObject params = body.getJSONObject("params");
            Collection<String> ids = Stream.of(params.getStr("id","null").split(",")).collect(Collectors.toList());
            boolean removeResult = wfUserService.removeByIds(ids);
            if(removeResult){
                result.toSuccess().setMessage("删除成功");
            }
        }
        return result;
    }

    /** 获取系统用户 */
    @GetMapping("/get/{id}")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_GET')")
    public Object get(@PathVariable("id")String id){
        Result<Object> result = Result.FAILURE().setMessage("查询失败");
        WfUser wfUser = wfUserService.getById(id);
        if(wfUser!=null){
            wfUser.setPassword(null);
            result.toSuccess().setRecord(wfUser).setMessage("查询成功");
        }
        return result;
    }

    /** 更新系统用户 */
    @PostMapping("/update")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_UPDATE')")
    public Object update(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("更新失败");
        if(body.containsKey("record")){
            JSONObject record = body.getJSONObject("record");
            WfUser wfUser = record.toBean(WfUser.class);
            boolean updateResult = wfUserService.updateById(wfUser);
            if(updateResult){
                result.toSuccess().setMessage("更新成功");
            }
        }
        return result;
    }

    /* 以下是用户角色部分 *************************************************************************************************/

    /** 分页查询已分配给系统用户的系统角色 */
    @PostMapping("/role/page")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_ROLE_PAGE')")
    public Object rolePage(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("角色查询失败");
        long current = 1L, size = 10L, total = 0L;
        if(body.containsKey("page")){
            JSONObject page = body.getJSONObject("page");
            current = page.getLong("current",current);
            size = page.getLong("size",size);
        }
        if(body.containsKey("params")){
            JSONObject params = body.getJSONObject("params");
            String userId = params.getStr("userId","null");
            IPage<WfRoleUser> page = wfRoleUserMapper.pageByUserId(
                    new Page<WfRoleUser>(current,size).addOrder(OrderItem.desc("PRIORITY")),
                    userId, new LambdaQueryWrapper<>());
            List<JSONObject> record = page.getRecords().stream().map(
                    wfRoleUser -> new JSONObject()
                            .set("id",wfRoleUser.getId())
                            .set("roleId",wfRoleUser.getRoleId())
                            .set("userId",wfRoleUser.getUserId())
                            .set("priority",wfRoleUser.getPriority())
                            .set("roleCode",wfRoleUser.getRole().getCode())
                            .set("roleName",wfRoleUser.getRole().getName())
            ).collect(Collectors.toList());
            result.toSuccess().setMessage("角色查询成功").setRecord(record).setPage(current,size,page.getTotal());
        }
        return result;
    }

    /** 分页查询未分配给系统用户的系统角色 */
    @PostMapping("/role/available")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_ROLE_AVAILABLE')")
    public Object roleAvailable(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("角色查询失败");
        long current = 1L, size = 10L, total = 0L;
        if(body.containsKey("page")){
            JSONObject page = body.getJSONObject("page");
            current = page.getLong("current",current);
            size = page.getLong("size",size);
        }
        if(body.containsKey("params")){
            JSONObject params = body.getJSONObject("params");
            String search = params.getStr("_search");
            String userId = params.getStr("userId","null");
            LambdaQueryWrapper<WfRole> queryWrapper = new LambdaQueryWrapper<>();
            if(StrUtil.isNotEmpty(search)){
                queryWrapper.like(WfRole::getName,search);
            }
            IPage<WfRole> page = wfRoleUserMapper.pageRoleAvailable(new Page<>(current,size),userId,queryWrapper);
            List<JSONObject> record = page.getRecords().stream().map(
                    wfRole -> new JSONObject()
                            .set("id",wfRole.getId())
                            .set("code",wfRole.getCode())
                            .set("name",wfRole.getName())
            ).collect(Collectors.toList());
            result.toSuccess().setMessage("角色查询成功").setRecord(record).setPage(current,size,page.getTotal());
        }
        return result;
    }

    /** 收回分配给系统用户的系统角色 */
    @PostMapping("/role/regain")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_ROLE_REGAIN')")
    public Object roleRegain(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("角色收回失败");
        if(body.containsKey("params")) {
            JSONObject params = body.getJSONObject("params");
            Set<String> idSet = params.getJSONArray("id")
                    .stream().map(StrUtil::toString).collect(Collectors.toSet());
            int deleted = wfRoleUserMapper.deleteBatchIds(idSet);
            if(deleted>=0){
                result.toSuccess().setMessage(String.format("成功收回%s个角色",deleted));
            }
        }
        return result;
    }

    /** 分配系统角色给系统用户 */
    @PostMapping("/role/allocate")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_ROLE_ALLOCATE')")
    public Object roleAllocate(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("角色分配失败");
        if(body.containsKey("params")) {
            JSONObject params = body.getJSONObject("params");
            String userId  = params.getStr("userId");
            Set<String> roleIdSet = params.getJSONArray("roleId")
                    .stream().map(StrUtil::toString).collect(Collectors.toSet());

            WfUser user = wfUserService.getById(userId);
            int priority = wfRoleUserMapper.nextPiority(userId);
            List<WfRole> roleList = wfRoleService.listByIds(roleIdSet);

            if(user!=null&&!roleList.isEmpty()){
                for(WfRole role:roleList){
                    WfRoleUser wfRoleUser = new WfRoleUser();
                    wfRoleUser.setUserId(user.getId());
                    wfRoleUser.setRoleId(role.getId());
                    wfRoleUser.setPriority(priority++);
                    wfRoleUserMapper.insert(wfRoleUser);
                }
                result.toSuccess().setMessage("角色分配成功");
            }
        }
        return result;
    }

    /** 调整分配给系统用户的系统角色优先级 */
    @PostMapping("/role/priority")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_ROLE_PRIORITY')")
    public Object rolePriority(@RequestBody JSONObject body) {
        Result<Object> result = Result.FAILURE().setMessage("优先级调整失败");
        if (body.containsKey("params")) {
            JSONObject params = body.getJSONObject("params");
            String id = params.getStr("id");
            boolean up = params.getBool("up");
            WfRoleUser wfRoleUser = wfRoleUserMapper.selectById(id);
            List<WfRoleUser> toUpdateList = new ArrayList<>();
            List<WfRoleUser> wfRoleUserList = wfRoleUserMapper.selectList(
                    new LambdaQueryWrapper<WfRoleUser>().eq(WfRoleUser::getUserId,wfRoleUser.getUserId()).orderByDesc(WfRoleUser::getPriority));
            for(int i=0;i<wfRoleUserList.size();i++){
                if(wfRoleUser.getId().equals(wfRoleUserList.get(i).getId())){
                    if(up){
                        WfRoleUser uppper = (i-1)>0?wfRoleUserList.get(i-1):null;
                        if(uppper!=null&&uppper.getPriority().equals(wfRoleUser.getPriority()+1)){
                            uppper.setPriority(uppper.getPriority()-1);
                            toUpdateList.add(uppper);
                        }
                        wfRoleUser.setPriority(wfRoleUser.getPriority()+1);
                        toUpdateList.add(wfRoleUser);
                    }else{
                        WfRoleUser lower = (i+1)<wfRoleUserList.size()?wfRoleUserList.get(i+1):null;
                        if(lower!=null&&lower.getPriority().equals(wfRoleUser.getPriority()-1)){
                            lower.setPriority(lower.getPriority()+1);
                            toUpdateList.add(lower);
                        }
                        wfRoleUser.setPriority(wfRoleUser.getPriority()-1);
                        toUpdateList.add(wfRoleUser);
                    }
                }
            }
            toUpdateList.forEach(wfRoleUserMapper::updateById);
            result.toSuccess().setMessage("优先级调整成功");
        }
        return result;
    }

    /* 以下是用户权限部分 *************************************************************************************************/

    /** 分页查询已分配给系统用户的系统权限 */
    @PostMapping("/prms/page")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_PRMS_PAGE')")
    public Object prmsPage(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("权限查询失败");
        long current = 1L, size = 10L, total = 0L;
        if(body.containsKey("page")){
            JSONObject page = body.getJSONObject("page");
            current = page.getLong("current",current);
            size = page.getLong("size",size);
        }
        if(body.containsKey("params")){
            JSONObject params = body.getJSONObject("params");
            String userId = params.getStr("userId","null");
            IPage<WfPrmsUser> page = wfPrmsUserMapper.pageByUserId(new Page<>(current,size),userId,new LambdaQueryWrapper<>());
            List<JSONObject> record = page.getRecords().stream().map(
                    wfPrmsUser -> new JSONObject()
                            .set("id",wfPrmsUser.getId())
                            .set("prmsId",wfPrmsUser.getPrmsId())
                            .set("userId",wfPrmsUser.getUserId())
                            .set("disabled",wfPrmsUser.getDisabled())
                            .set("prmsCode",wfPrmsUser.getPrms().getCode())
                            .set("prmsName",wfPrmsUser.getPrms().getName())
            ).collect(Collectors.toList());
            result.toSuccess().setMessage("权限查询成功").setRecord(record).setPage(current,size,page.getTotal());
        }
        return result;
    }

    /** 分页查询未分配给系统用户的系统权限 */
    @PostMapping("/prms/available")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_PRMS_AVAILABLE')")
    public Object prmsAvailable(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("权限查询失败");
        long current = 1L, size = 10L, total = 0L;
        if(body.containsKey("page")){
            JSONObject page = body.getJSONObject("page");
            current = page.getLong("current",current);
            size = page.getLong("size",size);
        }
        if(body.containsKey("params")){
            JSONObject params = body.getJSONObject("params");
            String search = params.getStr("_search");
            String userId = params.getStr("userId","null");
            LambdaQueryWrapper<WfPrms> queryWrapper = new LambdaQueryWrapper<>();
            if(StrUtil.isNotEmpty(search)){
                queryWrapper.like(WfPrms::getName,search);
            }
            IPage<WfPrms> page = wfPrmsUserMapper.pagePrmsAvailable(new Page<>(current,size),userId,queryWrapper);
            List<JSONObject> record = page.getRecords().stream().map(
                    wfRole -> new JSONObject()
                            .set("id",wfRole.getId())
                            .set("code",wfRole.getCode())
                            .set("name",wfRole.getName())
            ).collect(Collectors.toList());
            result.toSuccess().setMessage("权限查询成功").setRecord(record).setPage(current,size,page.getTotal());
        }
        return result;
    }

    /** 收回分配给系统用户的系统权限 */
    @PostMapping("/prms/regain")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_PRMS_REGAIN')")
    public Object prmsRegain(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("权限收回失败");
        if(body.containsKey("params")) {
            JSONObject params = body.getJSONObject("params");
            Set<String> idSet = params.getJSONArray("id")
                    .stream().map(StrUtil::toString).collect(Collectors.toSet());
            int deleted = wfPrmsUserMapper.deleteBatchIds(idSet);
            if(deleted>=0){
                result.toSuccess().setMessage(String.format("成功收回%s个权限",deleted));
            }
        }
        return result;
    }

    /** 分配系统权限给系统用户 */
    @PostMapping("/prms/allocate")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_PRMS_ALLOCATE')")
    public Object prmsAllocate(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("权限分配失败");
        if(body.containsKey("params")) {
            JSONObject params = body.getJSONObject("params");
            String userId  = params.getStr("userId");
            Set<String> prmsIdSet = params.getJSONArray("prmsId")
                    .stream().map(StrUtil::toString).collect(Collectors.toSet());

            WfUser user = wfUserService.getById(userId);
            List<WfPrms> prmsList = wfPrmsService.listByIds(prmsIdSet);

            if(user!=null&&!prmsList.isEmpty()){
                prmsList.forEach(prms->{
                    WfPrmsUser wfPrmsUser = new WfPrmsUser();
                    wfPrmsUser.setUserId(user.getId());
                    wfPrmsUser.setPrmsId(prms.getId());
                    wfPrmsUser.setDisabled(false);
                    wfPrmsUserMapper.insert(wfPrmsUser);
                });
                result.toSuccess().setMessage("权限分配成功");
            }
        }
        return result;
    }

    /** 禁用/启用分配给系统用户的系统权限 */
    @PostMapping("/prms/disable")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_PRMS_DISABLE')")
    public Object prmsDisable(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("权限禁用失败");
        if(body.containsKey("params")) {
            JSONObject params = body.getJSONObject("params");
            boolean disabled = params.getBool("disabled");
            Set<String> idSet = params.getJSONArray("id")
                    .stream().map(StrUtil::toString).collect(Collectors.toSet());
            WfPrmsUser entity = new WfPrmsUser();
            entity.setDisabled(disabled);
            int count = wfPrmsUserMapper.update(entity,new LambdaQueryWrapper<WfPrmsUser>().in(WfPrmsUser::getId,idSet));
            if(count>=0){
                result.toSuccess().setMessage(String.format("成功%s用%s个权限",disabled?"禁":"启",count));
            }
        }
        return result;
    }

    /* 以下是所有权限部分 *************************************************************************************************/

    /** 分页查询所有直接/间接分配给系统用户的系统权限 */
    @PostMapping("/prms/allocated")
    @PreAuthorize("hasAnyAuthority('ADMIN','API_USERPRMS_USER_PRMS_ALLOCATED')")
    public Object prmsAllPage(@RequestBody JSONObject body){
        Result<Object> result = Result.FAILURE().setMessage("权限查询失败");
        long current = 1L, size = 10L, total = 0L;
        if(body.containsKey("page")){
            JSONObject page = body.getJSONObject("page");
            current = page.getLong("current",current);
            size = page.getLong("size",size);
        }
        if(body.containsKey("params")){
            JSONObject params = body.getJSONObject("params");
            String userId = params.getStr("userId","null");
            IPage<Map<String,Object>> page = wfPrmsUserMapper.allocatedPrms(new Page<Map<String,Object>>(current,size).addOrder(OrderItem.desc("PRIORITY")),userId,new LambdaQueryWrapper<>());
            Map<String, WfPrmsActive> activeMap = wfPrmsUserMapper.activePrms(userId).stream().collect(Collectors.toMap(WfPrmsActive::getPrmsId, item->item));
            List<JSONObject> record = page.getRecords().stream().map(
                    map -> {
                        String remark = "";
                        WfPrmsActive active = activeMap.get(StrUtil.toString(map.get("PRMS_ID")));
                        if(active!=null&&"ROLE".equals(active.getType())&& NumberUtil.parseInt(StrUtil.toString(map.get("PRIORITY")))<active.getPriority()){
                            remark = String.format("该权限被优先级%s的角色“%s”覆盖为%s",active.getPriority(),active.getRoleName(),active.getDisabled()?"禁用":"启用");
                        }else if(active!=null&&"USER".equals(active.getType())&& NumberUtil.parseInt(StrUtil.toString(map.get("PRIORITY")))<active.getPriority()){
                            remark = String.format("该权限被用户权限配置覆盖为%s",active.getDisabled()?"禁用":"启用");
                        }
                        return new JSONObject()
                                .set("id",map.get("ID"))
                                .set("prmsId",map.get("PRMS_ID"))
                                .set("prmsCode",map.get("PRMS_CODE"))
                                .set("prmsName",map.get("PRMS_NAME"))
                                .set("type",map.get("TYPE"))
                                .set("disabled",map.get("DISABLED"))
                                .set("priority",map.get("PRIORITY"))
                                .set("roleId",map.get("ROLE_ID"))
                                .set("roleCode",map.get("ROLE_CODE"))
                                .set("roleName",map.get("ROLE_NAME"))
                                .set("remark",remark);
                    }
            ).collect(Collectors.toList());
            result.toSuccess().setMessage("权限查询成功").setRecord(record).setPage(current,size,page.getTotal());
        }
        return result;
    }

}
